package org.altervista.cp.thinjdbc;

import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

import org.altervista.cp.thinjdbc.wrappers.ResultSet;

public class DefaultLoadQuery extends LoadQuery<Map<String, Object>> {

	private static class DefaultResultSetMapper implements
			ResultSetMapper<Map<String, Object>> {
		public Map<String, Object> map(final ResultSet rsw) {

			final String[] keys;

			{
				keys = new String[rsw.getMetaData().getColumnCount()];
				for (int i = 0; i < keys.length; i++) {
					keys[i] = rsw.getMetaData().getColumnName(i + 1);
				}
			}

			if (_connected) {
				return new Map<String, Object>() {

					abstract class _Collection<E> implements Set<E> {

						public boolean add(E o) {
							throw new UnsupportedOperationException();
						}

						public boolean addAll(Collection<? extends E> c) {
							throw new UnsupportedOperationException();
						}

						public void clear() {
							throw new UnsupportedOperationException();
						}

						public boolean contains(Object o) {
							throw new UnsupportedOperationException();
						}

						public boolean containsAll(Collection<?> c) {
							throw new UnsupportedOperationException();
						}

						public boolean isEmpty() {
							return keys.length == 0;
						}

						public boolean remove(Object o) {
							throw new UnsupportedOperationException();
						}

						public boolean removeAll(Collection<?> c) {
							throw new UnsupportedOperationException();
						}

						public boolean retainAll(Collection<?> c) {
							throw new UnsupportedOperationException();
						}

						public int size() {
							return keys.length;
						}

						public Object[] toArray() {
							throw new UnsupportedOperationException();
						}

						public <T> T[] toArray(T[] a) {
							throw new UnsupportedOperationException();
						}
					}

					public void clear() {
						throw new UnsupportedOperationException();
					}

					public boolean containsKey(Object key) {
						for (int i = 0; i < keys.length; i++) {
							if (keys[i].equals(key)) {
								return true;
							}
						}
						return false;
					}

					public boolean containsValue(Object value) {
						throw new UnsupportedOperationException();
					}

					public Set<Entry<String, Object>> entrySet() {
						if (_entrySet == null) {
							_entrySet = new _Collection<Entry<String, Object>>() {
								public Iterator<Entry<String, Object>> iterator() {
									return new Iterator<Entry<String, Object>>() {

										public boolean hasNext() {
											return i < keys.length;
										}

										public Entry<String, Object> next() {
											i++;
											return new Entry<String, Object>() {
												public String getKey() {
													return keys[i - 1];
												}

												public Object getValue() {
													return rsw.getObject(i);
												}

												public Object setValue(
														Object value) {
													throw new UnsupportedOperationException();
												}
											};
										}

										public void remove() {
											throw new UnsupportedOperationException();
										}

										private int i = 0;

									};
								}
							};
						}
						return _entrySet;
					}

					public Object get(Object key) {
						return rsw.getObject(key.toString());
					}

					public boolean isEmpty() {
						return size() == 0;
					}

					public Set<String> keySet() {
						if (_keySet == null) {
							_keySet = new _Collection<String>() {
								public Iterator<String> iterator() {
									return new Iterator<String>() {

										public boolean hasNext() {
											return i < keys.length;
										}

										public String next() {
											return keys[i++];
										}

										public void remove() {
											throw new UnsupportedOperationException();
										}

										private int i = 0;

									};
								}
							};
						}
						return _keySet;
					}

					public Object put(String key, Object value) {
						throw new UnsupportedOperationException();
					}

					public void putAll(Map<? extends String, ? extends Object> t) {
						throw new UnsupportedOperationException();
					}

					public Object remove(Object key) {
						throw new UnsupportedOperationException();
					}

					public int size() {
						return keys.length;
					}

					public Collection<Object> values() {
						if (_values == null) {
							_values = new _Collection<Object>() {
								public Iterator<Object> iterator() {
									return new Iterator<Object>() {

										public boolean hasNext() {
											return i < keys.length;
										}

										public Object next() {
											return rsw.getObject(++i);
										}

										public void remove() {
											throw new UnsupportedOperationException();
										}

										private int i = 0;

									};
								}
							};
						}
						return _values;
					}

					private Set<Entry<String, Object>> _entrySet;
					private Collection<Object> _values;
					private Set<String> _keySet;

				};
			} else {
				LinkedHashMap<String, Object> resultMap = new LinkedHashMap<String, Object>();
				for (int i = 1, n = rsw.getMetaData().getColumnCount(); i <= n; i++) {
					resultMap.put(rsw.getMetaData().getColumnName(i), rsw
							.getObject(i));
				}
				return resultMap;
			}
		}

		private DefaultResultSetMapper(boolean connected) {
			_connected = connected;
		}

		private boolean _connected;
	};

	public DefaultLoadQuery(String sql) {
		this(sql, true);
	}

	public DefaultLoadQuery(String sql, boolean connected) {
		super(sql, new DefaultResultSetMapper(connected), connected);
	}

}
